﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.IO.Compression;
using Shell32;
using System.Runtime.InteropServices;

using DirectoryHelper;

namespace VSIX_Editor
{
    public partial class FrmVISXEditor : VSIX_Editor.FrmMain
    {
        string selectedVSIXPackage = string.Empty;
        TreeNode rootNode = null;

        DirectoryHelper.DirectoryHelper newDirectoryHelper = new DirectoryHelper.DirectoryHelper();

        public FrmVISXEditor()
        {
            InitializeComponent();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            if (dlgBrowseVSIX.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                txtSelection.Text = dlgBrowseVSIX.FileName;
                selectedVSIXPackage = Path.Combine(Path.GetTempPath(), Path.GetFileName(txtSelection.Text));

                try
                {
                    File.Copy(dlgBrowseVSIX.FileName, selectedVSIXPackage);
                }
                catch { }

                DisplayVSIXContents(selectedVSIXPackage);
            }
        }

        private void DisplayVSIXContents(string VSIXPackage)
        {
            string extractedVSIXLocation = ExtractVSIX(VSIXPackage);

            if (!extractedVSIXLocation.Equals(string.Empty))
            {
                tvwContents.Nodes.Clear();
                rootNode = new TreeNode();
                rootNode = tvwContents.Nodes.Add(Path.GetFileName (VSIXPackage));
                rootNode.Tag = extractedVSIXLocation;

                try
                {
                    newDirectoryHelper.WalkDirectory(rootNode, txtSelection.Text);
                }
                catch (Exception generalEX) { MessageBox.Show(generalEX.Message); }

                tvwContents.ExpandAll();
            }
        }        

        private string ExtractVSIX(string VSIXPackage)
        {
            if (File.Exists(VSIXPackage))
            {
                string extractionFolder = Path.Combine(Path.GetDirectoryName(VSIXPackage), "VSIXE_TMP_Extracted");
                if (Directory.Exists(extractionFolder))
                {
                    try
                    {
                        Directory.Delete(extractionFolder, true);
                    }
                    catch { }
                }

                Directory.CreateDirectory(extractionFolder);

                try
                {
                    ZipFile.ExtractToDirectory(VSIXPackage, extractionFolder);

                    return extractionFolder;
                }
                catch { }
            }

            return string.Empty;
        }

        private void btnAddFolder_Click(object sender, EventArgs e)
        {
            if (tvwContents.SelectedNode != null)
            {
                if (dlgBrowseOutput.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
                {
                    TreeNode selectedNode = tvwContents.SelectedNode;
                    string SelectedFolder2Add = dlgBrowseOutput.SelectedPath;
                    string SelectedFolder2AddName = SelectedFolder2Add.Replace(Path.GetDirectoryName(SelectedFolder2Add), string.Empty);
                    SelectedFolder2AddName = SelectedFolder2AddName.Replace("\\", string.Empty);
                    SelectedFolder2AddName = SelectedFolder2AddName.Replace("%20", " ");
                    TreeNode newNode = selectedNode.Nodes.Add(SelectedFolder2AddName);
                    newNode.Tag = SelectedFolder2Add;
                    newNode.ToolTipText = txtSelection.Text + "\\" + SelectedFolder2AddName;

                    try
                    {
                        newDirectoryHelper.WalkDirectory(newNode, selectedNode.Tag.ToString());
                    }
                    catch (Exception generalEX) { MessageBox.Show(generalEX.Message); }
                    
                    tvwContents.Sort();
                }
            }
        }

        private void btnAddFile_Click(object sender, EventArgs e)
        {
            if (tvwContents.SelectedNode != null)
            {
                if (dlgAddFile.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
                {
                    TreeNode selectedNode = tvwContents.SelectedNode;

                    foreach (var selectedFile in dlgAddFile.FileNames)
                    {
                        string FileName = Path.GetFileName(selectedFile);
                        FileName = FileName.Replace("\\", string.Empty);
                        FileName = FileName.Replace("%20", " ");
                        TreeNode newNode = selectedNode.Nodes.Add(FileName);
                        newNode.Tag = selectedFile;
                        newNode.ToolTipText = txtSelection.Text + "\\" + FileName;
                    }

                    tvwContents.Sort();
                }
            }
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            if (tvwContents.SelectedNode != null)
                tvwContents.Nodes.Remove(tvwContents.SelectedNode);
        }

        private void btnBack_Click(object sender, EventArgs e)
        {
            DisplayVSIXContents(selectedVSIXPackage);
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            if (tvwContents.Nodes.Count > 0)
            {
                if (dlgSaveVSIX.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
                {
                    string outputFolder = Path.GetDirectoryName(dlgSaveVSIX.FileName);
                    outputFolder = Path.Combine(outputFolder, "AR_VSIX_Combine");
                    Directory.CreateDirectory(outputFolder);
                    newDirectoryHelper.ExportVSIX(tvwContents.Nodes[0], outputFolder);

                    HouseKeep(dlgSaveVSIX.FileName);
                    string alternateZipOutputFile = dlgSaveVSIX.FileName.ToLowerInvariant ().Replace (".vsix", ".zip");
                    CreateArchive(outputFolder, alternateZipOutputFile);
                    MessageBox.Show("File created.");
                    try
                    {
                        File.Move(alternateZipOutputFile, dlgSaveVSIX.FileName);
                    }
                    catch { MessageBox.Show(this, "The file is created with the .zip extension. Please rename the same to .vsix for use.", "File creation operation succeeded with errors.", MessageBoxButtons.OK, MessageBoxIcon.Information); }                   
                    
                    HouseKeep(outputFolder);
                }
            }
        }

        private void CreateArchive(string srcFolder, string outputFileName)
        {
            if (File.Exists(outputFileName))
                File.Delete(outputFileName);
            
            // Create empty archive
            byte[] emptyzip = new byte[] { 80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

            FileStream fs = File.Create(outputFileName);
            fs.Write(emptyzip, 0, emptyzip.Length);
            fs.Flush();
            fs.Close();
            fs = null;

            //Copy a folder and its contents into the newly created zip file
            Shell32.ShellClass sc = new Shell32.ShellClass();
            Shell32.Folder SrcFlder = sc.NameSpace(srcFolder);
            Shell32.Folder DestFlder = sc.NameSpace(outputFileName);
            Shell32.FolderItems items = SrcFlder.Items();
            DestFlder.CopyHere(items, 20);

            System.Threading.Thread.Sleep(3000);
        }

        public Shell32.Folder GetShell32NameSpace(Object folder)
        {
            Type shellAppType = Type.GetTypeFromProgID("Shell.Application");
            Object shell = Activator.CreateInstance(shellAppType);
            return (Shell32.Folder)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, shell, new object[] { folder });
        }

        private void HouseKeep(string obj2HouseKeep)
        {
            try
            {
                Directory.Delete(obj2HouseKeep, true);
            }
            catch (Exception generalEX) { }

            try
            {
                File.Delete(obj2HouseKeep);
            }
            catch (Exception generalEX) { }
        }

        private void FrmVISXEditor_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                string extractionFolder = Path.Combine(Path.GetDirectoryName(selectedVSIXPackage), "VSIXE_TMP_Extracted");
                                
                HouseKeep(extractionFolder);
                HouseKeep(selectedVSIXPackage);
            }
            catch { }
        }
    }
}
